Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.

...powered by www.netzwerkartist.de...

 << zurück
Visual C# 2005 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual C# 2005

Visual C# 2005
1.320 S., mit 2 CDs, 59,90 Euro
Galileo Computing
ISBN 3-89842-586-X
gp Kapitel 6 Vererbung, Polymorphie und Schnittstellen
  gp 6.1 Basisklassen und abgeleitete Klassen
    gp 6.1.1 Ableiten einer Klasse
    gp 6.1.2 Klassen, die nicht vererben können
    gp 6.1.3 Zusammenfassung
  gp 6.2 Konstruktoren in abgeleiteten Klassen
    gp 6.2.1 Die Konstruktoren der Klasse »GraphicCircle«
    gp 6.2.2 Der Zugriffsmodifizierer »protected«
    gp 6.2.3 Konstruktorverkettung
    gp 6.2.4 Destruktor-Verkettung
    gp 6.2.5 Der Stand des Projekts »CircleApplication«
    gp 6.2.6 Zusammenfassung
  gp 6.3 Die Methoden in einer abgeleiteten Klasse
    gp 6.3.1 Geerbte Methoden mit »new« verdecken
    gp 6.3.2 Überladen einer Basisklassenmethode
  gp 6.4 Ereignisse in der Vererbung
  gp 6.5 »Hat-eine«-Beziehungen (Aggregation)
    gp 6.5.1 Weiterleitung einer internen Objektreferenz
    gp 6.5.2 Verbergen des internen Objekts
    gp 6.5.3 Innere Klassen
  gp 6.6 Typumwandlung von Objektvariablen
    gp 6.6.1 Die implizite Typumwandlung von Objektreferenzen
    gp 6.6.2 Die explizite Typumwandlung von Objektreferenzen
    gp 6.6.3 Zusammenfassung
  gp 6.7 Abstrakte Klassen und Methoden
    gp 6.7.1 Abstrakte Definitionen
  gp 6.8 Polymorphie
    gp 6.8.1 Virtuelle Methoden
    gp 6.8.2 Inhomogene Mengen
    gp 6.8.3 Verdecken und Überschreiben geerbter Methoden
    gp 6.8.4 Überschreiben der Methode »ToString()« der Klasse »Object«
    gp 6.8.5 Versiegelte Methoden
    gp 6.8.6 Zusammenfassung
  gp 6.9 Erweiterung der Klassenhierarchie »CircleApplication«
    gp 6.9.1 Die Klasse »GeometricObject«
  gp 6.10 Schnittstellen
    gp 6.10.1 Einführung in die Schnittstellen
    gp 6.10.2 Schnittstellendefinition
    gp 6.10.3 Schnittstellenimplementierung
    gp 6.10.4 Typumwandlung mit dem »as«-Operator
    gp 6.10.5 Abstrakte Klassen vs. Schnittstellen
    gp 6.10.6 Zusammenfassung


Galileo Computing

6.3 Die Methoden in einer abgeleiteten Klassdowntop

Klassen werden abgeleitet, um aus einer Klasse eine spezialisiertere mit weiteren, spezifischen Verhaltensweisen zu entwickeln. Dazu können in Subklassen neue Methoden implementiert werden, die über die der Basisklasse hinausgehen und Verhaltensweisen beschreiben, in der sich die Subklasse von ihrer Basisklasse unterscheidet. Die Methode Draw der Klasse GraphicCircle ist ein Beispiel dazu.

Die von der abgeleiteten Klasse aus der Basisklasse geerbten Methoden müssen nicht im Verhältnis 1:1 übernommen werden, sondern können auf abweichende Bedürfnisse oder Anforderungen angepasst werden. Dazu bietet das objektorientierte Konzept von C# das Verdecken (Ausblenden) und die Methodenüberladung an.


Galileo Computing

6.3.1 Geerbte Methoden mit »new« verdecken  downtop

Vom Verdecken oder Ausblenden einer Basisklassenmethode wird gesprochen, wenn in der abgeleiteten Klasse eine Methode implementiert wird,

gp  die den gleichen Namen und
gp  eine identische Parameterliste

besitzt wie eine Methode in der Basisklasse und diese durch eine eigene Implementierung vollständig ersetzt. Das ist beispielsweise der Fall, wenn die Implementierung in der Basisklasse für Objekte vom Typ der abgeleiteten Klasse falsch oder nicht wünschenswert ist. Wird eine Basisklassenmethode in der abgeleiteten Klasse ausgeblendet, wird beim Aufruf der Methode auf Objekte vom Typ der Subklasse immer die verdeckende Version ausgeführt. Entscheidend für das Verdecken einer geerbten Methode ist die Ergänzung der Methodendefinition um den Modifizierer new. Dem C#-Compiler teilen wir damit unsere Absicht mit.

Zur Verdeutlichung nehmen wir an, in der Klasse ClassA wäre die parameterlose Methode TestMethod enthalten:


class ClassA {
  public void TestMethod() {
    Console.WriteLine("ClassA.TestMethod()");
  }
}

Die Klasse ClassB wird aus ClassA abgeleitet. Nach den Regeln der Vererbung wird mit


class ClassB : ClassA {/* ... */}

zum Ausdruck gebracht, dass alle nicht private definierten Mitglieder von ClassA nun auch zu Mitgliedern von ClassB werden.

Man kann sich vorstellen, dass die ClassB sehr wohl ein Interesse an einer Methode namens TestMethod hat – allerdings mit einer anderen Implementierung. In der abgeleiteten Klasse muss daher die geerbte Methode der Basisklasse ausgeblendet und typspezifisch neu codiert werden. Wir können jetzt in ClassB mit


class ClassB : ClassA {
  public new void TestMethod() {
    Console.WriteLine("ClassB.TestMethod()");
  }
}

eine gleichnamige Methode mit identischer Signierung bereitstellen. Da sowohl der Name als auch die Parameterliste identisch mit der aus ClassA geerbten Methode sind, verdeckt TestMethod in ClassB die geerbte.

Wird TestMethod auf ein Objekt vom Typ ClassB mit


ClassB obj = new ClassB();
obj.TestMethod();

aufgerufen, wird die in der abgeleiteten Klasse definierte Methode ausgeführt, was im Befehlsfenster zu der Ausgabe


ClassB.TestMethod()

führt.


In gleicher Weise, wie eine geerbte Instanzmethode in einer ableitenden Klasse verdeckt werden kann, lassen sich mit new auch Eigenschaften, Felder und statische Komponenten einer Basisklasse ausblenden und durch eine typspezifische Implementierung ersetzen.

Verdecken statischer Methoden

Zu einem interessanten Ergebnis führt der new-Modifizierer, wenn in der Basisklasse eine Methode statisch definiert und in der abgeleiteten Klasse versucht wird, das statische Mitglied der Basisklasse durch ein Instanzmember zu ersetzen, beispielsweise:


class ClassA {
  public static void TestMethod(){...}
}
class ClassB : ClassA {
  public new void TestMethod(){...}
}

Wird ClassB instanziert, kann auf eine Referenz vom Typ ClassB die Instanzmethode aufgerufen werden und auf den Klassenbezeichner ClassB die statische Methode, die in der Basisklasse definiert ist und sich an die abgeleitete Klasse vererbt:


ClassB obj = new ClassB();
obj.TestMethod();
ClassB.TestMethod();

Etwas anders sieht das Ergebnis aus, wenn in der Basisklasse eine Methode als Instanzmethode definiert ist, die in der ableitenden Klasse durch eine statische Methode verdeckt wird:


class ClassA {
  public void TestMethod() {...}
}
class ClassB : ClassA {
  public static new void TestMethod() {...}
}

Auf die Typangabe ClassB kann auf die verdeckende, statische Version der Methode zugegriffen werden:


ClassB.TestMethod();

Instanziieren wir allerdings die Klasse ClassB, wird uns in der Intellisense-Auswahlliste die Instanzmethode angeboten, so dass wir zunächst ungestraft die folgende Anweisung schreiben können:


obj.TestMethod();

Erst der Compiler stellt fest, dass für ein Objekt vom Typ ClassB die Instanzmethode TestMethod nicht im Gültigkeitsbereich definiert ist, und bricht die Kompilierung mit einer Fehlermeldung ab.

Die Sichtbarkeit eines verdeckenden Klassenmitglieds

Zugriffsmodifizierer beschreiben die Sichtbarkeit eines Klassenmitglieds. Ein public deklariertes Mitglied ist über die Grenzen der aktuellen Assemblierung hinaus bekannt, während der Modifizierer internal die Sichtbarkeit auf die aktuelle Assemblierung beschränkt. private Klassenmitglieder hingegen sind nur in der definierenden Klasse sichtbar.

Ein verdeckendes Member muss nicht zwangsläufig denselben Zugriffsmodifizierer haben wie das Member der Basisklasse, das verdeckt wird. Deshalb darf die öffentliche Methode TestMethod der ClassA in der erbenden Klasse ClassB durch eine private deklarierte Methode ausgeblendet werden.


class ClassA {
  public void TestMethod() {
    Console.WriteLine("ClassA.TestMethod()");
  }
}
class ClassB : ClassA {
  private new void TestMethod() {
    Console.WriteLine("ClassB.TestMethod()");
  }
}

Dies führt dazu, dass die verdeckende Methode nur innerhalb von ClassB sichtbar ist, während der Aufruf von TestMethod auf ein Objekt vom Typ ClassB zu der am nächsten liegenden, gleichnamigen öffentlichen Methode in der Vererbungslinie führt:


ClassB obj = new ClassB();
obj.TestMethode();

Im Befehlsfenster wird


ClassA.TestMethod()

ausgegeben. Wir können daraus die Schlussfolgerung ziehen:


Das vollständige Ausblenden eines geerbten Mitglieds durch Privatisierung ist nicht möglich.

Zugriff auf Basisklassenmethoden mit »base«

Obwohl man die geerbte Methode einer Basisklasse verdeckt, um eine gleichnamige Methode mit klassenspezifischer Verhaltensweise in der abgeleiteten Klasse bereitzustellen, kann es unter Umständen sinnvoll sein, den Code aus der Basisklassenmethode zu nutzen, um deren Verhalten in der abgeleiteten Klasse zu übernehmen und passend zu erweitern.

Stellen wir uns dazu ein einfaches Beispiel vor. In der Klasse BaseClass sei die Methode GetNumbers definiert, die mit dem Zufallszahlengenerator Random zwei Zahlen im Bereich zwischen einschließlich 0 und 10 ermittelt und diese in Form eines Arrays an den Benutzer der Klasse zurückgibt.


class BaseClass {
  public int[] GetNumbers() {
    int[] arr = new int[2];
    Random rnd = new Random();
    for(int i = 0; i <= 1; i++)
      arr[i] = rnd.Next(11);
    return arr;
  }
}

Nehmen wir an, dass eine Klasse, die aus BaseClass abgeleitet wird, eine Methode GetNumbers enthalten soll, die ebenfalls zwei Zufallszahlen aus demselben Zahlenbereich erzeugen soll, jedoch mit dem Unterschied, dass das 0-indizierte Element grundsätzlich immer die kleinere der beiden Zahlen enthalten soll.

Wir könnten in der Methode der abgeleiteten Klasse denselben Code, wie er in der Methode der Basisklasse enthalten ist, noch einmal schreiben – aber sehr elegant ist diese Lösung nicht. Besser ist es, mit dem Schlüsselwort base auf das entsprechende Member in der Basisklasse zuzugreifen und dessen Verhalten zu übernehmen:


class DerivedClass : BaseClass {
  public new int[] GetNumbers() {    
    int[] arr = base.GetNumbers();
    if(arr[0] > arr[1]) {
      int temp;
      temp = arr[1];
      arr[1] = arr[0];
      arr[0] = temp;
    }
    return arr;
  }
}

Wir hatten base schon im Zusammenhang mit der Konstruktorverkettung kennen gelernt. Hier wird der Einsatz durch den Aufruf eines Mitglieds der direkten Basisklasse gezeigt:


int[] arr = base.GetNumbers();

GetNumbers in der Basisklasse liefert als Rückgabewert ein Array vom Typ int, der in arr entgegengenommen wird. Falls die Reihenfolge nicht den Anforderungen entspricht, wird zunächst die Hilfsvariable temp deklariert, die eines der beiden Array-Elemente während der Umschichtung der Werte kurzfristig zwischenspeichern soll.


Galileo Computing

6.3.2 Überladen einer Basisklassenmethode  toptop

Oft ist es notwendig, die von einer Basisklasse geerbten Methoden in der Subklasse zu überladen, um ein Objekt vom Typ der Subklasse an speziellere Anforderungen anzupassen. Von einer Methodenüberladung wird bekanntlich gesprochen, wenn sich zwei gleichnamige Methoden einer Klasse nur in ihrer Parameterliste unterscheiden. Derselbe Begriff hat sich geprägt, wenn eine geerbte Methode in der Subklasse nach den Regeln der Methodenüberladung ergänzt werden muss.

Im folgenden Beispiel ist die Klasse BaseClass definiert, die eine Methode namens GetValue veröffentlicht, die einen int-Wert entgegennimmt und im geschützten Feld intVar speichert:


class BaseClass {
  protected int intVar;
  public void GetValue(int x) {
    intVar = x;
  }
}

Die Klasse DerivedClass beerbt die Klasse BaseClass, implementiert allerdings eine von der geerbten Methode GetValue abweichende Parameterliste und überlädt diese:


class DerivedClass : BaseClass {
  private long lngVar;
  public void GetValue(int x, long y) {
    intVar = x;
    lngVar = y;
  }
}

Wird mit


DerivedClass obj = new DerivedClass();

ein Objekt vom Typ der abgeleiteten Klasse erzeugt, kann auf dessen Referenz mit zwei Methoden operiert werden, z.B.:


obj.GetValue(17);
obj.GetValue(2,3);

 << zurück
  
  Zum Katalog
Zum Katalog: Visual C# 2005
Visual C# 2005
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Fortgeschrittene Programmierung mit Visual C# 2005






 Fortgeschrittene
 Programmierung
 mit Visual C# 2005


Zum Katalog: Einstieg in Visual C# 2005






 Einstieg in
 Visual C# 2005


Zum Katalog: Einstieg in Visual Basic 2005






 Einstieg in
 Visual Basic 2005


Zum Katalog: Visual Basic 2005






 Visual Basic 2005


Zum Katalog: Java ist auch eine Insel






 Java ist auch eine
 Insel


Zum Katalog: Konzepte und Lösungen für Microsoft-Netzwerke






 Konzepte und
 Lösungen für
 Microsoft-Netzwerke


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo








Copyright © Galileo Press 2006
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de